package com.itwxz.games.service.impl;

import com.itwxz.common.core.domain.R;
import com.itwxz.common.core.redis.RedisCache;
import com.itwxz.common.exception.ServiceException;
import com.itwxz.common.utils.ServletUtils;
import com.itwxz.common.utils.bean.BeanUtils;
import com.itwxz.common.utils.ip.IpUtils;
import com.itwxz.games.domain.undercover.URoom;
import com.itwxz.games.domain.werewolf.WCreateRoomInfo;
import com.itwxz.games.domain.werewolf.WIdentity;
import com.itwxz.games.domain.werewolf.WPost;
import com.itwxz.games.domain.werewolf.WRoom;
import com.itwxz.games.service.WerewolfService;
import com.itwxz.games.utils.CreateIdUtils;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@RequiredArgsConstructor
public class WerewolfServiceImpl implements WerewolfService {
    private final CreateIdUtils cId;
    private final RedisCache redisCache;

    @Override
    public WRoom createRoom(WCreateRoomInfo info) {
        // 生成房间对象
        WRoom room = BeanUtils.copyBean(info, WRoom.class);
        room.setRoomId(cId.getWCRoomId());

        List<WIdentity> idList = new ArrayList<>();
        for (WPost post : room.getPostList()) {
            for (int i = 0; i < post.getPeoples(); i++) {
                WIdentity identity = WIdentity.builder()
                        .id(0)
                        .name(post.getName())
                        .joined(false)
                        .build();
                idList.add(identity);
            }
        }

        Collections.shuffle(idList);

        int i = 1;
        for (WIdentity id : idList) {
            id.setId(i++);
        }

        room.setIdentities(idList);

        // 存入 Redis，两小时过期
        redisCache.setCacheObject(
                cId.getWKeyPrefix() + room.getRoomId(),
                room, 2, TimeUnit.HOURS);
        log.info(room.toString());
        return room;
    }

    @Override
    public WIdentity joinRoom(String roomId) {
        // Redis key 和锁 key
        String key = cId.getWKeyPrefix() + roomId;
        String lockKey = "lock:werewolf:room:" + roomId; // 每个房间独立的锁键

        // 尝试加锁，最多等待 5 秒
        if (!redisCache.tryLock(lockKey, 5, TimeUnit.SECONDS)) {
            return WIdentity.builder()
                    .id(0) // 表示加入失败
                    .build();
        }

        try {
            // 从 Redis 获取房间
            WRoom room = redisCache.getCacheObject(key);
            if (room == null) {
                throw new ServiceException("房间不存在或已过期");
            }

            // 打乱身份列表
            Collections.shuffle(room.getIdentities());

            // 找出第一个未加入的身份
            WIdentity available = room.getIdentities().stream()
                    .filter(i -> i.getJoined() == null || !i.getJoined())
                    .findFirst()
                    .orElse(null);

            if (available == null)
                throw new ServiceException("房间已满");


            // 分配身份
            available.setRoomId(Long.valueOf(roomId));
            available.setJoined(true);
            available.setIp(IpUtils.getIpAddr());

            // 浏览器和操作系统信息
            final UserAgent userAgent = UserAgent.parseUserAgentString(
                    ServletUtils.getRequest().getHeader("User-Agent")
            );
            available.setBrowser(userAgent.getBrowser().getName());
            available.setOs(userAgent.getOperatingSystem().getName());

            // 更新 Redis，TTL 2 小时
            redisCache.setCacheObject(key, room, 2, TimeUnit.HOURS);

            return available;
        } finally {
            // 确保释放锁
            redisCache.unlock(lockKey);
        }
    }

    @Override
    public R<Boolean> checkRoom(String roomId) {
        if (roomId == null || roomId.trim().isEmpty()) {
            return R.ok(false);
        }
        String key = cId.getWKeyPrefix() + roomId.trim();
        WRoom WRoom = redisCache.getCacheObject(key);

        if (WRoom == null) return R.ok(false);

        return R.ok(true);
    }

    @Override
    public R<Boolean> closeRoom(String roomId) {
        String key = cId.getWKeyPrefix() + roomId;
        if (redisCache.deleteObject(key)) {
            log.info("房间 {} 已关闭", roomId);
        }
        return R.ok(true);
    }
}
